<?php
// +----------------------------------------------------------------------
// | Status 状态服务
// +----------------------------------------------------------------------
// | 主要服务于Status数据处理
// +----------------------------------------------------------------------
// | 错误编码头 224xxx
// +----------------------------------------------------------------------

namespace common\service;

use common\model\StatusModel;
use support\SingletonTrait;

class StatusService
{
    /**
     * @var \common\Model\StatusModel
     */
    private $statusModel;

    // 单例工具
    use SingletonTrait;

    protected $statusData = [];
    protected array $byId = [];
    protected array $byCode = [];

    public function __construct()
    {
        $this->statusModel = model(StatusModel::class);

        $this->statusData = $this->statusModel->cache(C('database.default_query_cache_time'))->select();
        $this->byId = array_column($this->statusData, null, 'id');
        $byCodeList = array_column($this->statusData, null, 'code');
        $this->byCode = array_map(function ($tmp) {
            $tmp['id'] = intval($tmp['id']);
            return $tmp;
        }, $byCodeList);
    }

    public function byCode(string $statusCode, string $column = null)
    {
        if (!empty($column)) {
            return $this->byCode[$statusCode][$column] ?? null;
        }
        return $this->byCode[$statusCode] ?? null;
    }

    /**
     * @param array $statusCodeList
     * @param bool $exclude
     * @param string|null $implodeKey
     * @return array|string
     */
    public function byCodeMap(array $statusCodeList, bool $exclude = false, string $implodeKey = null)
    {
        $res = [];
        if (!$exclude) {
            foreach ($statusCodeList as $code) {
                if (isset($this->byCode[$code])) {
                    $res[$code] = $this->byCode[$code];
                }
            }
        } else {
            foreach ($this->byCode as $code => $item) {
                if (!in_array($code, $statusCodeList)) {
                    $res[$code] = $item;
                }
            }
        }
        if (!empty($implodeKey)) {
            return implode(',', array_column($res, $implodeKey));
        }
        return $res;
    }

    /**
     * 把状态按照Correspond分类
     * @param string $correspond
     * @return array|mixed
     */
    public function getCorrespondStatusIds($correspond = '')
    {
        $allStatusData = $this->statusModel->selectData(['fields' => 'id,correspond']);
        $correspondStatusData = [];
        foreach ($allStatusData['rows'] as $allStatusItem) {
            if (array_key_exists($allStatusItem['correspond'], $correspondStatusData)) {
                array_push($correspondStatusData[$allStatusItem['correspond']], $allStatusItem['id']);
            } else {
                $correspondStatusData[$allStatusItem['correspond']] = [$allStatusItem['id']];
            }
        }
        if (!empty($correspond)) {
            return $correspondStatusData[$correspond];
        } else {
            return $correspondStatusData;
        }
    }

    /**
     * 获取状态id分组通过状态从属关系
     * @return array
     */
    public function getStatusIdGroupByCorrespond()
    {
        $allStatusData = $this->statusModel->field('id,correspond')->cache(C('database.default_query_cache_time'))->select();

        $allGroupIdData = [
            'blocked' => [],
            'not_started' => [],
            'in_progress' => [],
            'daily' => [],
            'feedback' => [],
            'done' => [],
            'hide' => []
        ];
        foreach ($allStatusData as $statusItem) {
            $allGroupIdData[$statusItem['correspond']][] = $statusItem['id'];
        }

        return $allGroupIdData;
    }

    /**
     * 获得一条状态
     * @param $filter
     * @param $fields
     * @return mixed
     */
    public function getOne($filter, $fields)
    {
        return $this->statusModel->where($filter)->field($fields)->cache(C('database.default_query_cache_time'))->find();
    }

    /**
     * 获得多条状态
     * @param $filter
     * @param $fields
     * @return mixed
     */
    public function getList($filter, $fields)
    {
        return $this->statusModel->where($filter)->field($fields)->cache(C('database.default_query_cache_time'))->select();
    }

    /**
     * 获得实体已发布状态列表
     * @param $moduleCode
     * @return mixed
     */
    public function getEntityPublishedStatusList($moduleCode)
    {
        switch ($moduleCode) {
            case 'design':
            case 'asset':
            case 'level':
            case 'shot':
            case 'storyboard':
            case 'sequence':
            default:
                $codeList = [
                    'task_generated',
                    'inprogress',
                    'final',
                ];
        }
        return $this->getList(['code' => ['IN', implode(',', $codeList)]], "*");
    }

    /**
     * 状态列表
     * @param string $moduleCode
     * @param string $subModuleCode
     * @return array|array[]
     */
    public function entityStatusList(string $moduleCode, string $subModuleCode)
    {
        $res = [];
        switch ($moduleCode) {
            case 'design':
                $res = [
                    [
                        'id' => 0,
                        'name' => '待发布',
                        'code' => 'wait_publish',
                        'code_list' => ['second_add_finished', 'wait_for_add', 'first_add_finished', 'wait_for_second_add', 'ready_to_publish'],
                        'code_id_list' => [$this->byCode['second_add_finished']['id'], $this->byCode['wait_for_add']['id'], $this->byCode['first_add_finished']['id'], $this->byCode['wait_for_second_add']['id'], $this->byCode['ready_to_publish']['id']],
                    ],
                    [
                        'id' => 1,
                        'name' => '进行中',
                        'code' => 'inprogress',
                        'code_list' => ['inprogress',],
                        'code_id_list' => [$this->byCode['inprogress']['id'],]
                    ],
                    [
                        'id' => 2,
                        'name' => '已完成',
                        'code' => 'final',
                        'code_list' => ['final',],
                        'code_id_list' => [$this->byCode['final']['id'],],
                    ],
                    [
                        'id' => 3,
                        'name' => '已取消',
                        'code' => 'closed',
                        'code_list' => ['closed',],
                        'code_id_list' => [$this->byCode['closed']['id'],],
                    ],
                    [
                        'id' => 4,
                        'name' => '未开始',
                        'code' => 'not_started',
                        'code_list' => ['task_generated',],
                        'code_id_list' => [$this->byCode['task_generated']['id'],],
                    ],
                ];
                break;
            case 'storyboard':
                switch ($subModuleCode) {
                    case 'motion_sequence':
                        $res = [
                            [
                                'id' => 0,
                                'name' => '未开始',
                                'code' => 'not_started',
                                'code_list' => ['not_started'],
                                'code_id_list' => [$this->byCode['not_started']['id'],],
                            ],
                            [
                                'id' => 1,
                                'name' => '进行中',
                                'code' => 'inprogress',
                                'code_list' => ['inprogress'],
                                'code_id_list' => [$this->byCode['inprogress']['id'],],
                            ],
                            [
                                'id' => 1,
                                'name' => '已完成',
                                'code' => 'final',
                                'code_list' => ['final'],
                                'code_id_list' => [$this->byCode['final']['id'],],
                            ],
                        ];
                        break;
                    case 'sequence':
                        $res = [
                            [
                                'id' => 0,
                                'name' => '待生成任务',
                                'code' => '',
                                'code_list' => ['wait_for_generated'],
                                'code_id_list' => [$this->byCode['wait_for_generated']['id'],],
                            ],
                            [
                                'id' => 1,
                                'name' => '已生成任务',
                                'code' => 'published',
                                'code_list' => ['task_generated', 'inprogress', 'final'],
                                'code_id_list' => [$this->byCode['task_generated']['id'], $this->byCode['inprogress']['id'], $this->byCode['final']['id']],
                            ],
                        ];
                        break;
                    case 'shot':
                        $res = [
                            [
                                'id' => 0,
                                'name' => '待发布',
                                'code' => 'wait_for_merge_sequence',
                                'code_list' => ['wait_for_merge_sequence'],
                                'code_id_list' => [$this->byCode['wait_for_merge_sequence']['id'],],
                            ],
                            [
                                'id' => 1,
                                'name' => '进行中',
                                'code' => 'inprogress',
                                'code_list' => ['inprogress', 'wait_for_generated',],
                                'code_id_list' => [$this->byCode['inprogress']['id'], $this->byCode['wait_for_generated']['id']],
                            ],
                            [
                                'id' => 2,
                                'name' => '已完成',
                                'code' => 'final',
                                'code_list' => ['final',],
                                'code_id_list' => [$this->byCode['final']['id']],
                            ],
                            [
                                'id' => 3,
                                'name' => '已取消',
                                'code' => 'closed',
                                'code_list' => ['closed',],
                                'code_id_list' => [$this->byCode['closed']['id']],
                            ],
                            [
                                'id' => 4,
                                'name' => '未开始',
                                'code' => 'not_started',
                                'code_list' => ['task_generated',],
                                'code_id_list' => [$this->byCode['task_generated']['id']],
                            ],
                        ];
                    default:
                }
                break;
            default:
                $res = [];
        }
        return $res;
    }

    /**
     * 需求状态列表
     * @return array|false|mixed|string
     */
    public function entityDemandStatusList()
    {
        $res = model(StatusModel::class)->where(['code' => ['IN', ['wait_demand', 'already_relate']]])->select();
        if (empty($res)) {
            return [];
        }
        return $res;
    }

    /**
     * 获得待甲方审核状态
     * @return mixed|null
     */
    public function getTaskWaitForPartyAReviewStatus()
    {
        $code = OptionsService::getInstance()->getOptionsConfigItemData("default_task_status", "default_client_review_status");
        if (empty($code)) {
            return null;
        }
        return $this->getOne(['code' => $code], "*");
    }

    /**
     * 获得待乙方提交状态
     * @return mixed|null
     */
    public function getTaskWaitForPartyBSubmitReviewStatus()
    {
        return $this->getOne(['code' => 'wait_partyb_submit'], "*");
    }

    /**
     * 获得任务默认客户审核状态
     * @return array
     */
    public function getTaskClientReviewStatus()
    {
        $code = OptionsService::getInstance()->getOptionsConfigItemData("default_task_status", "default_client_review_status");
        if (empty($code)) {
            return null;
        }
        return $this->getOne(['code' => $code], "*");
    }

    /**
     * 获得任务默认状态
     * @return array
     */
    public function getTaskReviewRejectStatus()
    {
        $code = OptionsService::getInstance()->getOptionsConfigItemData("default_task_status", "default_reject_status");
        if (empty($code)) {
            return null;
        }
        return $this->getOne(['code' => $code], "*");
    }

    /**
     * 查询任务默认状态列表排查指定项
     * @param array $excludeCode
     * @return array|mixed
     */
    public function getTaskDefaultStatusWithExclude(array $excludeCode = [])
    {
        $statusList = OptionsService::getInstance()->getTaskStatusList();
        if (empty($excludeCode)) {
            return $statusList;
        }
        $newStatusList = [];
        foreach ($statusList as $statusItem) {
            if (!in_array($statusItem['code'], $excludeCode)) {
                $newStatusList[] = $statusItem;
            }
        }
        return $newStatusList;
    }

    /**
     * 获取默认审核中状态
     * @return mixed|null
     */
    public function getTaskDefaultReviewingStatus()
    {
        $code = OptionsService::getInstance()->getOptionsConfigItemData("default_task_status", "default_reviewing_status");
        if (empty($code)) {
            return null;
        }
        return $this->getOne(['code' => $code], "*");
    }


    /**
     * 查询任务默认就绪状态
     * @return mixed|null
     */
    public function getTaskDefaultReadyStatus()
    {
        $code = OptionsService::getInstance()->getOptionsConfigItemData("default_task_status", "default_ready_status");
        if (empty($code)) {
            return null;
        }
        return $this->getOne(['code' => $code], "*");
    }

    /**
     * 查询任务外组装状态
     * @return mixed|null
     */
    public function getTaskWaitAssembleStatus()
    {
        return $this->getOne(['code' => 'wait_assemble'], "*");
    }

    /**
     * 获得未开始任务状态列表
     * @return array
     */
    public function getNotStartedStatus()
    {
        $configList = OptionsService::getInstance()->getOptionsConfigMultiItemData('default_task_status', ['default_status', 'default_ready_status', 'default_wait_assemble_status']);
        $codeList = array_values($configList);
        return $this->getList(['code' => ['IN', implode(',', $codeList)]], "*");
    }

    /**
     * 获得任务默认状态
     * @return array
     */
    public function getTaskDefaultStatus()
    {
        $code = OptionsService::getInstance()->getOptionsConfigItemData("default_task_status", "default_status");
        if (empty($code)) {
            return null;
        }
        return $this->getOne(['code' => $code], "*");
    }

    /**
     * 获得任务默认完成状态
     * @return array
     */
    public function getTaskDoneStatus()
    {
        $code = OptionsService::getInstance()->getOptionsConfigItemData("default_task_status", "default_completion_status");
        if (empty($code)) {
            return null;
        }
        return $this->getOne(['code' => $code], "*");
    }

    /**
     * 获得任务默认待发布状态
     * @return array
     */
    public function getTaskReadyToPublishStatus()
    {
        $code = OptionsService::getInstance()->getOptionsConfigItemData("default_task_status", "default_release_status");
        if (empty($code)) {
            return null;
        }
        return $this->getOne(['code' => $code], "*");
    }

    /**
     * 获得任务默认审核通过状态
     * @return array
     */
    public function getTaskReviewPassStatus()
    {
        $code = OptionsService::getInstance()->getOptionsConfigItemData("default_task_status", "default_approval_status");
        if (empty($code)) {
            return null;
        }
        return $this->getOne(['code' => $code], "*");
    }

    /**
     * 获得任务默认开始状态
     * @return array
     */
    public function getTaskDefaultStartStatus()
    {
        $code = OptionsService::getInstance()->getOptionsConfigItemData("default_task_status", "default_start_status");
        return $this->getOne(['code' => $code], "*");
    }

    /**
     * 获得任务默认等待组装状态
     * @return mixed
     * @throws \Exception
     */
    public function getTaskDefaultWaitAssembleStatus()
    {
        $code = OptionsService::getInstance()->getOptionsConfigItemData("default_task_status", "default_wait_assemble_status");
        return $this->getOne(['code' => $code], "*");
    }

    /**
     * 获得任务默认返修状态
     * @return mixed
     */
    public function getTaskDefaultRemakeStatus()
    {
        $code = OptionsService::getInstance()->getOptionsConfigItemData("default_task_status", "default_remake_status");
        return $this->getOne(['code' => $code], "*");
    }

    /**
     * 获得多条状态 map
     * @param $filter
     * @param $fields
     * @param $by
     * @return array
     */
    public function getMapBy($filter, $fields, $by)
    {
        $list = $this->getList($filter, $fields);
        return array_column($list, null, $by);
    }

    /**
     * 获得默认启用状态
     * @return mixed
     */
    public function getTaskDefaultClosedStatus()
    {
        $code = OptionsService::getInstance()->getOptionsConfigItemData("default_task_status", "default_deprecate_status");
        return $this->getOne(['code' => $code], "*");
    }

    /**
     * 获得默认草稿状态
     * @return mixed
     */
    public function getDefaultDraftStatus()
    {
        $code = OptionsService::getInstance()->getOptionsConfigItemData("default_task_status", "default_draft_status");
        return $this->getOne(['code' => $code], "*");
    }

    /**
     * 查询默认状态
     * @param string $name
     * @return mixed|null
     */
    public function getDefaultStatus(string $name)
    {
        $code = OptionsService::getInstance()->getOptionsConfigItemData("default_task_status", $name);
        if (empty($code)) {
            return null;
        }
        return $this->getOne(['code' => $code], "*");

    }
}
